package com.itemp.ms66btreceiver;

import androidx.appcompat.app.AppCompatActivity;

import android.Manifest;
import android.annotation.SuppressLint;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import org.w3c.dom.Text;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * MS66 超市货架电子价签
 * Jachary 2025.2.27
 */
public class MainActivity extends AppCompatActivity {
    private String TAG = "BTReceiver";
    private final String UUIDs = "00001101-0000-1000-8000-00805F9B34FB";
    private boolean listening;
    private BluetoothAdapter bluetoothAdapter;
    private TextView title_textview;
    private TextView wifi_ip_textview;
    private TextView btMacTextView;
    private ImageView btMacImageView;
    private BluetoothSocket serverSocket;
    private AcceptThread acceptThread;
    private int state;
    private int STATE_DISCONNECTED = 0;
    private int STATE_CONNECTED = 1;
    private BluetoothServerSocket btserver = null;
    private String btMacAddress;
    private ImageView no_wifi_iv;

    @SuppressLint({"MissingInflatedId", "MissingPermission"})
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        requestPermission();

        /*String SSID = getIntent().getStringExtra("ssid");
        String password = getIntent().getStringExtra("password");
        Log.d(TAG,"get wifi config : " + SSID + "\n" + password);
        connectDefaultWifi(SSID,password);*/

//        BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
//        bluetoothAdapter = bluetoothManager.getAdapter();
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        btMacAddress = bluetoothAdapter.getAddress();
        btMacTextView = findViewById(R.id.bt_mac_tv);
        btMacTextView.setText(btMacAddress);
        btMacImageView = findViewById(R.id.bt_mac_qr_iv);
        Bitmap bitmap = Utils.createQRCodeBitmap(btMacAddress, 245, 245, "UTF-8", "H", "1", Color.BLACK, Color.WHITE);
        btMacImageView.setImageBitmap(bitmap);

        title_textview = findViewById(R.id.title_textview);
        wifi_ip_textview = findViewById(R.id.wifi_ip_textview);
        no_wifi_iv = findViewById(R.id.no_wifi_iv);

        if (bluetoothAdapter != null) {
            if (!bluetoothAdapter.isEnabled()) {
                bluetoothAdapter.enable();
            }
        }
        Intent intent = new Intent("com.android.setDiscoverable");
        intent.setPackage("com.android.settings");
        sendBroadcast(intent);

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        registerReceiver(mReceiver, intentFilter);

        IntentFilter intentFilter2 = new IntentFilter();
        intentFilter2.addAction(Intent.ACTION_MEDIA_MOUNTED);
        intentFilter2.addDataScheme("file");
        registerReceiver(mountReceiver, intentFilter2);
    }

    private BroadcastReceiver mountReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_MEDIA_MOUNTED.equals(intent.getAction())) {
                String mountPath = intent.getData().getPath();
                Log.d(TAG, "mountPath = " + mountPath);
                File wifiConfigFile = new File(mountPath, "wifi.config");
                if (wifiConfigFile.exists()) {
                    String wifiConfig = readFile(wifiConfigFile.getAbsolutePath());
                    //"WIFI_SSID;password123456"
                    Log.d(TAG, "wifiConfig:" + wifiConfig);
                    if (!TextUtils.isEmpty(wifiConfig)) {
                        String[] arrs = wifiConfig.split(";");
                        if (arrs != null && arrs.length > 1) {
                            String SSID = arrs[0];
                            String password = arrs[1];
                            Log.d(TAG, "WIFI CONFIG: " + SSID + "\n" + password);
                            connectDefaultWifi(SSID,password);
                        }
                    }
                }
            }
        }
    };

    private String readFile(String filePathName) {
        StringBuffer stringBuffer = new StringBuffer();
        FileInputStream fileInputStream;
        try {
            fileInputStream = new FileInputStream(filePathName);
            byte[] buffer = new byte[1024];
            int len = fileInputStream.read(buffer);
            while (len > 0) {
                stringBuffer.append(new String(buffer, 0, len));
                len = fileInputStream.read(buffer);
            }
            fileInputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return stringBuffer.toString();
    }


    private BroadcastReceiver pairReceiver = new BroadcastReceiver() {
        @SuppressLint("MissingPermission")
        @Override
        public void onReceive(Context context, Intent intent) {
            if (BluetoothDevice.ACTION_PAIRING_REQUEST.equals(intent.getAction())) {
                abortBroadcast();
                BluetoothDevice bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                int passKey = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_KEY, BluetoothDevice.ERROR);
                if (bluetoothDevice != null && passKey != BluetoothDevice.ERROR) {
                    bluetoothDevice.setPairingConfirmation(true);
                }
            }
        }
    };

    private BroadcastReceiver netWorkReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = cm.getActiveNetworkInfo();
            if (networkInfo != null
                    && networkInfo.isConnected()
                    && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                closeSocket();
                if (acceptThread != null) {
                    acceptThread.interrupt();
                    acceptThread = null;
                }
                no_wifi_iv.setVisibility(View.GONE);
                Log.d(TAG, "Network is connected");
                getWifiIpAddress();

                finish();
            } else {
                Log.d(TAG, "Network is disconnected");
//                wifi_ip_textview.setText("Network is disconnected");
                no_wifi_iv.setVisibility(View.VISIBLE);
            }
        }
    };

    private void getWifiIpAddress() {
        ConnectivityManager connManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connManager.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
            WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
            int ipAddress = wifiInfo.getIpAddress();
            String ipString = intToIp(ipAddress);
            String wifiSSID = wifiInfo.getSSID();
            wifi_ip_textview.setText("WIFI: " + wifiSSID + "\n" +"IP Address: " + ipString);
        }
    }

    private String intToIp(int ipAddress) {
        return (ipAddress & 0xFF) + "." +
                ((ipAddress >> 8) & 0xFF) + "." +
                ((ipAddress >> 16) & 0xFF) + "." +
                (ipAddress >> 24 & 0xFF);
    }

    @Override
    protected void onStart() {
        super.onStart();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(netWorkReceiver, intentFilter);
        listening = true;
        startServerSocket();
    }

    @Override
    protected void onResume() {
        super.onResume();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
        intentFilter.setPriority(1000);
        registerReceiver(pairReceiver, intentFilter);
    }


    @Override
    protected void onStop() {
        super.onStop();
        listening = false;
        unregisterReceiver(netWorkReceiver);
        closeSocket();

        if (acceptThread != null) {
            acceptThread.interrupt();
            acceptThread = null;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        unregisterReceiver(mReceiver);
        unregisterReceiver(mountReceiver);
    }

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) {
                int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.ERROR);
                switch (bondState) {
                    case BluetoothDevice.BOND_NONE:
                        break;
                    case BluetoothDevice.BOND_BONDING:
                        break;
                    case BluetoothDevice.BOND_BONDED:
                        break;
                }
            } else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
                // 设备已连接
                Log.d(TAG, "ACTION_ACL_CONNECTED");
            } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
                // 设备已断开
                Log.d(TAG, "ACTION_ACL_DISCONNECTED");
                cleanData();
            }
        }
    };

    private void cleanData(){
        ArrayList<String> packageNames = new ArrayList();
        packageNames.add("com.itemp.ms66btreceiver");
        Intent intent2 = new Intent("com.itemp.clear_user_data");
        intent2.putStringArrayListExtra("packageNames", packageNames);
        intent2.setPackage("com.android.settings");
        sendBroadcast(intent2);
    }

    @SuppressLint("MissingPermission")
    private void setDiscoverableTimeout(int timeout, int mode) {
        if (mode == 1) {
            Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
            discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, timeout);
            startActivity(discoverableIntent);
        } else {
            try {
                //利用反射使用 setDiscoverableTimeout和setScanMode
                Method setDiscoverableTimeout = BluetoothAdapter.class.getMethod("setDiscoverableTimeout", int.class);
                setDiscoverableTimeout.setAccessible(true);
                Method setScanMode = BluetoothAdapter.class.getMethod("setScanMode", int.class, int.class);
                setScanMode.setAccessible(true);
                if (mode == 2) {
                    //静默式 timeout不起作用，会一直保持可见性
                    setDiscoverableTimeout.invoke(bluetoothAdapter, 300);
                    setScanMode.invoke(bluetoothAdapter, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, 300);
                    //mHandler.sendEmptyMessageDelayed(5, 300000);//300秒后发送5类信号让Handler关闭蓝牙可见性
                } else if (mode == 3) {
                    //实现关闭蓝牙可见性
                    setDiscoverableTimeout.invoke(bluetoothAdapter, 1);
                    setScanMode.invoke(bluetoothAdapter, BluetoothAdapter.SCAN_MODE_CONNECTABLE, 1);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private class AcceptThread extends Thread {
        @SuppressLint("MissingPermission")
        @Override
        public void run() {
            super.run();
            UUID uuid = UUID.fromString(UUIDs);
            String name = "bluetoothserver";
            try {
                btserver = bluetoothAdapter.listenUsingRfcommWithServiceRecord(name, uuid);
            } catch (IOException e) {
                e.printStackTrace();
            }
            while (listening) {
                Log.d(TAG, "BluetoothServerSocket wait...");
                try {
                    if (btserver != null) {
                        serverSocket = btserver.accept();
                    }
                    if (serverSocket != null) {
                        listenForMessages(serverSocket);
                    }
//                    runOnUiThread(() -> {
//                        Toast.makeText(MainActivity.this, "Bluetooth Disconnected", Toast.LENGTH_LONG).show();
//                    });
                } catch (IOException e) {
                    closeSocket();
                }
            }
        }
    }

    private void closeSocket() {
        if (serverSocket != null) {
            try {
                serverSocket.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            serverSocket = null;
        }
    }

    private void startServerSocket() {
        closeSocket();
        if (acceptThread != null) {
            acceptThread.interrupt();
            acceptThread = null;
        }
        acceptThread = new AcceptThread();
        acceptThread.start();

    }

    private void sendMessage(BluetoothSocket socket, String message) {
        OutputStream outStream;
        try {
            outStream = socket.getOutputStream();
            byte[] byteArray = (message + " ").getBytes();
            byteArray[byteArray.length - 1] = 0;
            outStream.write(byteArray);
        } catch (IOException e) {
        }
    }

    private void listenForMessages(BluetoothSocket socket) {

        int bufferSize = 1024;
        byte[] buffer = new byte[bufferSize];
        try {
            InputStream instream = socket.getInputStream();
            int bytesRead = -1;
            while (listening) {
                bytesRead = instream.read(buffer);
                if (bytesRead != -1) {
                    String result = "";
                    while ((bytesRead == bufferSize) && (buffer[bufferSize - 1] != 0)) {
                        result = result + new String(buffer, 0, bytesRead - 1);
                        bytesRead = instream.read(buffer);
                    }
                    result = result + new String(buffer, 0, bytesRead - 1);
                    String finalResult = result;
                    runOnUiThread(() -> {
                        if (!TextUtils.isEmpty(finalResult)) {
                            String[] tempArr = finalResult.split(";");
                            if (tempArr.length > 1) {
                                connectDefaultWifi(tempArr[0], tempArr[1]);
                            }
                        }
                        Log.d(TAG, "BT Receiver:" + finalResult);
                        title_textview.setText(finalResult);
                    });
                }
            }

        } catch (IOException e) {
            if (serverSocket != null) {
                try {
                    serverSocket.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
                serverSocket = null;
            }
        }
    }

    private WifiManagerUtils wifiManagerUtils;

    private void connectDefaultWifi(String ssid, String psw) {
        if (TextUtils.isEmpty(ssid) || TextUtils.isEmpty(psw)) {
            return;
        }
        wifiManagerUtils = new WifiManagerUtils(this);
        if (wifiManagerUtils.checkWifiState() != WifiManager.WIFI_STATE_ENABLED) {
            if (wifiManagerUtils.openWifiEnabled()) {
                Log.d("yu", "WIFI_STATE_ENABLED!");
            }
        }
        WifiInfo wifiInfo = wifiManagerUtils.getNetWorkId();
        if (TextUtils.isEmpty(wifiInfo.getSSID())) {
            List<ScanResult> scanResults = wifiManagerUtils.getScanResult();
            for (ScanResult sr : scanResults) {
                if (sr.SSID.equals(ssid)) {
                    connectWifi(sr.SSID, psw);
                    break;
                }
            }
        } else {
            if (!wifiInfo.getSSID().equals(ssid)) {
                wifiManagerUtils.disconnectWifi(wifiInfo.getNetworkId());
                connectWifi(ssid, psw);
            }
        }
    }

    private void connectWifi(String ssid, String psw) {
        boolean result = wifiManagerUtils.addNetWork(wifiManagerUtils.createWifiInfo(ssid, psw, 3));
        if (result) {
            Log.d("yu", ssid + " connected!");
        } else {
            Log.d("yu", "connect failed!");
        }
    }


    public void requestPermission() {
        if (Build.VERSION.SDK_INT >= 23) {
            ArrayList<String> permissionsList = new ArrayList<>();
            String[] permissions = {
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.ACCESS_WIFI_STATE,
                    Manifest.permission.CHANGE_WIFI_STATE,
                    Manifest.permission.BLUETOOTH,
                    Manifest.permission.BLUETOOTH_ADMIN,
                    Manifest.permission.BLUETOOTH_CONNECT,
                    Manifest.permission.BLUETOOTH_SCAN,
                    Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.BLUETOOTH_ADVERTISE,
                    Manifest.permission.ACCESS_FINE_LOCATION};
            for (String perm : permissions) {
                if (PackageManager.PERMISSION_GRANTED != checkSelfPermission(perm)) {
                    permissionsList.add(perm);
                }
            }
            if (!permissionsList.isEmpty()) {
                String[] strings = new String[permissionsList.size()];
                requestPermissions(permissionsList.toArray(strings), 0);
            }
        }
    }


}